package com.ruoyi.finance.protal.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.pagehelper.util.StringUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.finance.livestreaming.entity.*;
import com.ruoyi.finance.livestreaming.mapper.*;
import com.ruoyi.finance.livestreaming.service.FiDigitalLivestreamingUserService;
import com.ruoyi.finance.livestreaming.service.IFiDigitalLivestreamingService;
import com.ruoyi.finance.livestreaming.vo.CounterChargeVO;
import com.ruoyi.finance.protal.constans.SystemConstant;
import com.ruoyi.finance.protal.service.ProtalUserService;
import com.ruoyi.finance.protal.utils.*;
import com.ruoyi.finance.rules.entity.SzOtherRule;
import com.ruoyi.finance.rules.entity.SzPromotionTree;
import com.ruoyi.finance.rules.entity.SzPromotionTreeVO;
import com.ruoyi.finance.rules.entity.SzUser;
import com.ruoyi.finance.rules.mapper.SzPromotionTreeMapper;
import com.ruoyi.finance.rules.mapper.SzUserMapper;
import com.ruoyi.finance.rules.task.SZRuleCache;
import com.ruoyi.module.utils.BigDecimalChain;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.Transient;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ProtalUserServiceImpl implements ProtalUserService {


    @Autowired
    private SzUserMapper szUserMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SzPromotionTreeMapper szPromotionTreeMapper;

    @Autowired
    private SzUserSession userSession;

    @Autowired
    private SZRuleCache ruleCache;

    @Autowired
    private SzOrderMapper szOrderMapper;

    @Autowired
    private IFiDigitalLivestreamingService fiDigitalLivestreamingService;

    @Autowired
    private FiDigitalLivestreamingMapper fiDigitalLivestreamingMapper;

    @Autowired
    private QiniuUtils qiniuUtils;

    @Autowired
    private SzUserBankCardMapper szUserBankCardMapper;

    @Autowired
    private SzWithdrawalRecordMapper szWithdrawalRecordMapper;

    @Autowired
    private FiDigitalLivestreamingUserService fiDigitalLivestreamingUserService;

    @Autowired
    private SzWithdrawalDetailMapper szWithdrawalDetailMapper;

    @Value("${protal.defaulAvatar}")
    private  String defaulAvatar;

    @Value("${protal.defaultPassword}")
    private  String defaultPassword;

    @Value("${protal.defaultPaymentPassword}")
    private  String defaultPaymentPassword;


    @Override
    public AjaxResult login(SzUser user, HttpServletRequest request) {
        if (StringUtil.isEmpty(user.getPhone()) || StringUtil.isEmpty(user.getPassword())){
            return AjaxResult.error("手机号/密码不能为空");
        }

        List<SzUser> szUsers = szUserMapper.selectList(new LambdaQueryWrapper<SzUser>()
                .eq(SzUser::getPhone, user.getPhone())
                .eq(SzUser::getIsSignOut, "0")
                .eq(SzUser::getDeleteFlag, "0"));

        if (szUsers.size() != 1){
            return AjaxResult.error("用户不存在");
        }

        if (!szUsers.get(0).getPassword().equals(user.getPassword())){
            return AjaxResult.error("密码错误");
        }

        SzUser logUser = szUsers.get(0);

        logUser.setLastLoginIp(IpUtils.getIpAddr(request));
        logUser.setLastLoginTime(LocalDateTime.now());
        szUserMapper.updateById(logUser);

        // 生成标识用户信息的随机id  有效期2小时
        String ticket = UUID.uuid();
        redisTemplate.opsForValue().set(SystemConstant.getLoginUserPrefix() + ticket, logUser.getId(), 604800,TimeUnit.SECONDS);
        return AjaxResult.success("登录成功",ticket);
    }

    @Override
    @Transient
    public AjaxResult register(SzUser user) {
        if (StringUtil.isEmpty(user.getNickname())){
            return AjaxResult.error("昵称不能为空");
        }

        if (StringUtil.isEmpty(user.getPhone()) || StringUtil.isEmpty(user.getPassword()) || StringUtil.isEmpty(user.getConfirmPassword())){
            return AjaxResult.error("手机号/密码不能为空");
        }

        if (!user.getPassword().equals(user.getConfirmPassword())){
            return AjaxResult.error("两次密码输入不一致");
        }

        Object code = redisTemplate.opsForValue().get(SystemConstant.getRegisterPrefix() + user.getPhone());
        if (ObjectUtil.isEmpty(code)){
            return AjaxResult.error("验证码错误");
        }

        if (!user.getVerificationCode().equals(code.toString())){
            return AjaxResult.error("验证码错误");
        }

        if (szUserMapper.selectCount(new LambdaQueryWrapper<SzUser>().eq(SzUser::getPhone, user.getPhone()).eq(SzUser::getIsSignOut, "0").eq(SzUser::getDeleteFlag,"0")) != 0){
            return AjaxResult.error("该手机号已被注册");
        }

        Long parentId = null;
        if (StringUtil.isNotEmpty(user.getInvitationParent())){
            parentId = this.getParentInvitationCode(user.getInvitationParent());
        }
        this.checkAccountHistory(user.getPhone());

        // 设置注册信息
        user.setAccountType("2"); // 商户
        user.setRegisterTime(LocalDateTime.now());
        user.setRecharge("0"); // 没参加过充值
        user.setWithdrawalLimitMonth(BigDecimal.ZERO);
        user.setBaseGoldBalance(BigDecimal.ZERO);
        user.setWelfareGoldBalance(BigDecimal.ZERO);
        user.setWelfareWithdrawalBalance(BigDecimal.ZERO);
        user.setInvitationCode(this.getInvitationCode());
        user.setInvitationParent(user.getInvitationParent());
        user.setSzWalletBalance(BigDecimal.ZERO);
        user.setSzWithdrawalBalance(BigDecimal.ZERO);
        user.setSzTeamReward(BigDecimal.ZERO);
        user.setSzRangeReward(BigDecimal.ZERO);
        user.setSzLateralReward(BigDecimal.ZERO);
        user.setSzRepeatbuyReword(BigDecimal.ZERO);
        user.setSzEnergy(BigDecimal.ZERO);
        user.setSzEnable("0");
        user.setAvatar(defaulAvatar);
        user.setVoucher(BigDecimal.ZERO);
        user.setDeductionAmount(BigDecimal.ZERO);
        user.setFrozenAccount(BigDecimal.ZERO);
        user.setPendingActivationBalance(BigDecimal.ZERO);
        user.setIsSignOut("0");
        user.setIsFrozen("0");
        szUserMapper.insert(user);

        if (parentId != null){
            SzPromotionTree tree = new SzPromotionTree();
            tree.setUserId(user.getId());
            tree.setParentId(parentId);
            tree.setCreateTime(LocalDateTime.now());
            szPromotionTreeMapper.insert(tree);
        }

        redisTemplate.delete(SystemConstant.getRegisterPrefix() + user.getPhone());
        return AjaxResult.success("注册成功");
    }

    private void checkAccountHistory(String phone) {
        SzUser user = szUserMapper.selectOne(new LambdaQueryWrapper<SzUser>().eq(SzUser::getPhone, phone));
        if (Objects.nonNull(user)){
            if ("1".equals(user.getIsSignOut())){
                user.setPhone(user.getPhone() + "(已注销)");
                szUserMapper.updateById(user);
            }

            if ("1".equals(user.getDeleteFlag())){
                user.setPhone(user.getPhone() + "(账号已删除)");
                szUserMapper.updateById(user);
            }
        }

    }

    @Override
    public AjaxResult SendRegisterCode(String phone) {
        if (StringUtil.isEmpty(phone)){
            return AjaxResult.error("手机号为空");
        }

        String code = UUID.generateValidateCode(6);
        if (SMSConstantUtils.sendPhone(code, phone)){
            redisTemplate.opsForValue().set(SystemConstant.getRegisterPrefix() + phone, code, 900,TimeUnit.SECONDS);
        }
        return AjaxResult.success("发送成功");
    }

    @Override
    public AjaxResult getInfo(HttpServletRequest request) {
        Long userId = userSession.getCurrentUserId(request);
        Map<String, Object> user = szUserMapper.getInfo(userId);

        SzOtherRule otherRule = ruleCache.getOtherRule();
        Map<String, Object> rule = new LinkedHashMap<>();
        rule.put("pricing", otherRule.getPricing());

        SzUserBankCard bankInfo = szUserBankCardMapper.getBankInfo(userId);

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("userInfo", user);
        result.put("rule", rule);
        result.put("bankInfo", bankInfo);
        return AjaxResult.success(result);
    }

    @Transient
    @Override
    public AjaxResult saveSzOrder(HttpServletRequest request) {
        SzOtherRule otherRule = ruleCache.getOtherRule();
        SzUser user = userSession.getCurrentUserInfo(request);
        log.info("用户点击支付    开始保存订单");

        // 保存平台订单记录
        SzOrder order = this.saveSystemOrderRecord(otherRule, user);
        log.info("平台订单保存成功：" + order.getOrderDescription());

        // 获取支付相关 生成支付二维码
        log.info("生成支付二维码");
        String encodeAddress = ShanDeCreateOrder.orderCreate(order);
        log.info("生成二维码路径为：{}", encodeAddress);

        // 将图片转为base64并返回
        try {
            return AjaxResult.success()
                    .put("PaymentQRCode", ImageToBase64Converter.convertToBase64(encodeAddress))
                    .put("orderId", order.getOrderId())
                    .put("orderName", order.getOrderName())
                    .put("orderDescription", order.getOrderDescription())
                    .put("expirationTime", order.getExpirationTime());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return AjaxResult.error();
    }

    @Override
    public AjaxResult orderPolling(String orderId, HttpServletRequest request) {
        if (StringUtil.isEmpty(orderId)){
            return AjaxResult.error("订单号为空");
        }

        SzOrder order = szOrderMapper.selectOne(new LambdaQueryWrapper<SzOrder>()
                .eq(SzOrder::getOrderId, orderId)
                .le(SzOrder::getRechargeTime, LocalDateTime.now())
                .ge(SzOrder::getExpirationTime, LocalDateTime.now()));

        if (order == null){
            return AjaxResult.success(false);
        }

        if (order.getPayState().equals("5") || order.getPayState().equals("3")){
            return AjaxResult.success(true);
        }

        return AjaxResult.success(false);
    }

    @Override
    @Transactional
    public Map<String, String> receiveNotice(JSONObject dataJson ) {
        Map<String, String> result = new LinkedHashMap<>();
        try {
            JSONObject head = dataJson.getJSONObject("head");
            JSONObject body = dataJson.getJSONObject("body");

            if (SystemConstant.ShanDSuccessCode.equals(head.getString("respCode"))){

                if (SystemConstant.ShanDOrderSuccessStatus.equals(body.getString("orderStatus"))){

                    String orderId = body.getString("tradeNo");// 交易流水号
                    log.info("交易流水号{}", orderId);

                    SzOrder order = szOrderMapper.selectOne(new LambdaQueryWrapper<SzOrder>().eq(SzOrder::getOrderId, orderId));
                    if (order == null){
                        log.error("订单状态修改失败，无此订单：{}", order);
                        result.put("respCode", "500000");
                    }else{
                        order.setPaymentTime(LocalDateTime.now());
                        order.setPayState("5");
                        order.setMid(body.getString("mid"));
                        order.setSettleAmount(this.convertStringToBigDecimal(body.getString("settleAmount")));
                        order.setAccLogonNo(body.getString("accLogonNo"));
                        order.setBuyerPayAmount(this.convertStringToBigDecimal(body.getString("buyerPayAmount")));
                        order.setPayId(body.getString("orderCode"));
                        order.setPaymentTime(this.convertToDateTime(body.getString("payTime")));
                        int i = szOrderMapper.updateById(order);
                        log.info("买家订单状态修改完毕");
                        log.info("准备执行业务");
                        fiDigitalLivestreamingService.purchaseOrder(order.getUserId().toString(), "7", order);

                        result.put("respCode", "000000");
                    }
                }else{
                    log.error("杉德支付-订单状态失败，商户订单号:{}", body.getString("orderCode"));
                    result.put("respCode", "500000");
                }

            }else{
                log.error("杉德支付回调接口报错");
                result.put("respCode", "500000");
            }


        }catch (Exception e){
            result.put("respCode", "500000");
        }
        return result;
    }

    /**
     * 支付成功，充值
     * @param dataJson
     * @return
     */
    @Override
    @Transactional
    public Map<String, String> receiveNoticePay(JSONObject dataJson ) {
        Map<String, String> result = new LinkedHashMap<>();
        try {
            JSONObject head = dataJson.getJSONObject("head");
            JSONObject body = dataJson.getJSONObject("body");

            if (SystemConstant.ShanDSuccessCode.equals(head.getString("respCode"))){

                if (SystemConstant.ShanDOrderSuccessStatus.equals(body.getString("orderStatus"))){

                    String orderId = body.getString("tradeNo");// 交易流水号
                    log.info("交易流水号{}", orderId);

                    SzOrder order = szOrderMapper.selectOne(new LambdaQueryWrapper<SzOrder>().eq(SzOrder::getOrderId, orderId));
                    if (order == null){
                        log.error("订单状态修改失败，无此订单：{}", order);
                        result.put("respCode", "500000");
                    }else{
                        order.setPaymentTime(LocalDateTime.now());
                        order.setPayState("3");
                        order.setMid(body.getString("mid"));
                        order.setSettleAmount(this.convertStringToBigDecimal(body.getString("settleAmount")));
                        order.setAccLogonNo(body.getString("accLogonNo"));
                        order.setBuyerPayAmount(this.convertStringToBigDecimal(body.getString("buyerPayAmount")));
                        order.setPayId(body.getString("orderCode"));
                        order.setPaymentTime(this.convertToDateTime(body.getString("payTime")));
                        int i = szOrderMapper.updateById(order);
                        log.info("买家订单状态修改完毕");
                        log.info("准备执行业务");
                        // fiDigitalLivestreamingService.purchaseOrder(order.getUserId().toString(), "7", order);
                        //充值，不购买产品
                        fiDigitalLivestreamingService.topUp(order);

                        result.put("respCode", "000000");
                    }
                }else{
                    log.error("杉德支付-订单状态失败，商户订单号:{}", body.getString("orderCode"));
                    result.put("respCode", "500000");
                }

            }else{
                log.error("杉德支付回调接口报错");
                result.put("respCode", "500000");
            }


        }catch (Exception e){
            result.put("respCode", "500000");
        }
        return result;
    }

    @Override
    public AjaxResult createOrderH5(HttpServletRequest request, HttpServletResponse response) {
        SzUser userInfo = userSession.getCurrentUserInfo(request);
        SzOtherRule otherRule = ruleCache.getOtherRule();

        Long parnetId = null;
        if (StringUtil.isNotEmpty(userInfo.getInvitationParent())){
            parnetId = szUserMapper.selectList(new LambdaQueryWrapper<SzUser>().eq(SzUser::getInvitationCode, userInfo.getInvitationParent())).get(0).getId();
        }

        // 创建系统订单
        SzOrder order = this.saveSystemOrderRecord(otherRule, userInfo, parnetId);
        log.info("平台订单保存成功：" + order.getOrderDescription());

        // 构建请求参数
        Map<String, String> respJson = ShanDeCreateOrderH5.orderCreate(request, response, order);
        return AjaxResult.success(respJson);
    }

    /**
     *  H5 余额变动详情
     * @param userId
     * @return
     */
    @Override
    public AjaxResult balanceDetailAdmin(String userId) {
        if (Objects.isNull(userId)){
            return AjaxResult.success("用户id为空");
        }

        List<Map<String, Object>> list = fiDigitalLivestreamingMapper.balanceDetailAdmin(Long.valueOf(userId));
        Map<String, BigDecimal> amount = fiDigitalLivestreamingMapper.getUserWalletAmount(Long.valueOf(userId));

        Map<String, Object> data = new LinkedHashMap<>();
        data.put("list", list);
        data.put("amount", amount);
        return AjaxResult.success(data);
    }

    @Override
    public AjaxResult uploadPicture(MultipartFile file, HttpServletRequest request) {
        if (file == null){
            return AjaxResult.error("头像为空");
        }

        SzUser userInfo = userSession.getCurrentUserInfo(request);
        String upload = qiniuUtils.upload(file);

        userInfo.setAvatar(upload);
        szUserMapper.updateById(userInfo);
        return AjaxResult.success("上传成功",upload);
    }


    private SzOrder saveSystemOrderRecord(SzOtherRule otherRule, SzUser user, Long parentId) {
        szOrderMapper.updateOrderState();

        // 判断是否已有未支付订单
        List<SzOrder> orderList = szOrderMapper.selectList(new LambdaQueryWrapper<SzOrder>()
                .eq(SzOrder::getUserId, user.getId())
                .le(SzOrder::getRechargeTime, LocalDateTime.now())
                .ge(SzOrder::getExpirationTime, LocalDateTime.now())
                .eq(SzOrder::getPayState, "1"));
        if (CollectionUtils.isNotEmpty(orderList)){
            szOrderMapper.delete(new LambdaQueryWrapper<SzOrder>()
                    .eq(SzOrder::getUserId, user.getId())
                    .le(SzOrder::getRechargeTime, LocalDateTime.now())
                    .ge(SzOrder::getExpirationTime, LocalDateTime.now())
                    .eq(SzOrder::getPayState, "1"));
        }


        // 创建新订单
        String orderId = com.ruoyi.finance.protal.utils.UUID.getCustomerOrderNo();
        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        SzOrder order = new SzOrder();
        order.setUserId(user.getId());
        order.setBuyType(user.getSzEnable().equals("0") ? "1" : "2");
        order.setEnergy(otherRule.getEnergy());
        order.setRechargeAmount(otherRule.getPricing());
        order.setRechargeTime(LocalDateTime.now());
        order.setOrderName((user.getSzEnable().equals("0") ? "开通" : "复购" + "数字人直播"));
        order.setOrderDescription(user.getNickname() + (user.getSzEnable().equals("0") ? "开通" : "复购" + "数字人直播") +  nowTime);
        order.setOrderId(orderId);
        order.setPaymentType("8");
        order.setPayState("1");
        order.setExpirationTime(LocalDateTime.now().plusDays(1));
        order.setParentId(parentId);
        szOrderMapper.insert(order);
        return order;
    }

    /**
     * 保存平台订单记录
     */
    private SzOrder saveSystemOrderRecord(SzOtherRule otherRule, SzUser user){
        szOrderMapper.updateOrderState();

        // 判断是否已有未支付订单
        List<SzOrder> orderList = szOrderMapper.selectList(new LambdaQueryWrapper<SzOrder>()
                .eq(SzOrder::getUserId, user.getId())
                .le(SzOrder::getRechargeTime, LocalDateTime.now())
                .ge(SzOrder::getExpirationTime, LocalDateTime.now())
                .eq(SzOrder::getPayState, "1"));
        if (CollectionUtils.isNotEmpty(orderList)){
            return orderList.get(0);
        }

        // 创建新订单
        String orderId = UUID.getCustomerOrderNo();
        SzOrder order = new SzOrder();
        order.setUserId(user.getId());
        order.setBuyType(user.getSzEnable().equals("0") ? "1" : "2");
        order.setEnergy(otherRule.getEnergy());
        order.setRechargeAmount(otherRule.getPricing());
        order.setRechargeTime(LocalDateTime.now());
        order.setOrderName((user.getSzEnable().equals("0") ? "开通" : "复购" + "数字人直播"));
        order.setOrderDescription(user.getNickname() + (user.getSzEnable().equals("0") ? "开通" : "复购" + "数字人直播") + LocalDateTime.now().toString() );
        order.setOrderId(orderId);
        order.setPayState("1");
        order.setExpirationTime(LocalDateTime.now().plusDays(1));
        return order;
    }

    // 注册时，生成一个随机邀请码
    private String getInvitationCode() {
        String invitationCode;
        Integer count;
        do {
            invitationCode = UUID.getInvitationCode();
            count = szUserMapper.selectCount(new LambdaQueryWrapper<SzUser>().eq(SzUser::getInvitationCode, invitationCode));
        } while (count > 0);

        return invitationCode;
    }

    // 上级用户邀请码
    private Long getParentInvitationCode(String invitationParent){
        List<SzUser> szUsers = szUserMapper.selectList(new LambdaQueryWrapper<SzUser>().eq(SzUser::getInvitationCode, invitationParent));
        if (szUsers.size() != 1){
            throw new IllegalStateException("邀请码错误");
        }

        return szUsers.get(0).getId();
    }

    private static BigDecimal convertStringToBigDecimal(String amountString) {
        BigDecimal amount = new BigDecimal(amountString);
        return amount.movePointLeft(2);
    }

    private static LocalDateTime convertToDateTime(String payTime) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        return LocalDateTime.parse(payTime, formatter);
    }

    /**
     * 数据直播对冲
     * @param fromUser
     * @param toUser
     * @return
     */
    @Override
    public AjaxResult mutualRecharge(String fromUser, String toUser){
        if (StringUtil.isNotEmpty(fromUser) && StringUtil.isNotEmpty(toUser)){
            return fiDigitalLivestreamingService.mutualRecharge(fromUser, toUser);
        }else{
            return AjaxResult.error();
        }
    }

    /**
     * 查询用户简单信息
     * @return
     */
    @Override
    public List<Map<String, String>> listSzUserSimple(String nickname) {
        return szUserMapper.listSzUserSimple("",nickname);
    }

    /**
     * H5 数据直播对冲
     * @param counterChargeVO
     * @return
     */
    @Override
    public AjaxResult mutualRechargeFree(CounterChargeVO counterChargeVO) {
        return fiDigitalLivestreamingService.mutualRechargeFree(counterChargeVO);
    }

    /**
     * 数字直播对冲提现余额
     * @param fromUser
     * @param toUser
     * @param money
     * @param paymentPassword
     * @return
     */
    @Override
    public AjaxResult mutualRechargeBalance(String fromUser, String toUser, BigDecimal money, String paymentPassword) {
        return fiDigitalLivestreamingService.mutualRechargeBalance(fromUser, toUser, money, paymentPassword);
    }

    /**
     * 打赏
     * @param userId
     * @param rewardedUser
     * @param giftId
     * @param price
     * @param count
     * @return
     */
    @Override
    public AjaxResult rewardWithGifts(Long userId, Long rewardedUser, Long giftId, BigDecimal price, BigDecimal count) {
        return fiDigitalLivestreamingUserService.rewardWithGifts(userId,rewardedUser,giftId,price,count);
    }


    /**
     * 个人中心-查询下级用户
     * @param request
     * @return
     */
    @Override
    public SzPromotionTreeVO userInviteTree(HttpServletRequest request) {
        SzPromotionTreeVO szPromotionTreeVO = new SzPromotionTreeVO();
        BigDecimal totalTeamMoney=BigDecimal.ZERO;
        List<SzPromotionTree> list = fiDigitalLivestreamingService.userInviteTree(userSession.getCurrentUserId(request))
                .stream().peek(szPromotionTree -> {
                    szPromotionTree.setId(null);
                    szPromotionTree.setUserId(null);
                    szPromotionTree.setParentId(null);
                    szPromotionTree.setChildren(null);
                }).collect(Collectors.toList());
        szPromotionTreeVO.setList(list);
        if (CollUtil.isNotEmpty(list)){
            for (SzPromotionTree szPromotionTree : list) {
                totalTeamMoney=totalTeamMoney.add(Objects.nonNull(szPromotionTree.getMoneySum())?szPromotionTree.getMoneySum():BigDecimal.ZERO);
            }
        }
        szPromotionTreeVO.setTotalTeamMoney(totalTeamMoney);
        return szPromotionTreeVO;
    }



    /**
     * 用户购买记录 h5
     * @param userId
     * @return
     */
    @Override
    public Map<String, Object> purchaseRecord(Long userId) {
        return fiDigitalLivestreamingService.purchaseRecord(userId);
    }

    /**
     * 购买数字直播
     * @param userId
     * @param parentId
     * @return
     */
    @Override
    public AjaxResult buyLivestreaming(String userId, String parentId) {
        if (StringUtil.isEmpty(parentId) || "null".equals(parentId) || "undefined".equals(parentId)){
            return fiDigitalLivestreamingService.buyProduct(userId);
        }else{
            return fiDigitalLivestreamingService.buyProductByInvite(userId, parentId);
        }
    }

    /**
     * 用户可提现余额细明
     * @param userId
     * @return
     */
    @Override
    public Map<String, Object> withdrawalBalance(Long userId) {
        return fiDigitalLivestreamingService.withdrawalBalance(userId);
    }

    @Override
    public AjaxResult saveBankCard(String realName, String cardId, String bankName, String bankAddress, HttpServletRequest request) {
        Long currentUserId = userSession.getCurrentUserId(request);

        if (szUserBankCardMapper.selectCount(new LambdaQueryWrapper<SzUserBankCard>()
                .eq(SzUserBankCard::getUserId, currentUserId).eq(SzUserBankCard::getDeleteFlag, "0")) != 0){
            return AjaxResult.error("只能绑定一张银行卡");
        }

        szUserBankCardMapper.insert(new SzUserBankCard()
                .setUserId(currentUserId)
                .setCardId(cardId)
                .setBankName(bankName)
                .setBankAddress(bankAddress)
                .setRealName(realName)
                .setCreateTime(LocalDateTime.now())
                .setDeleteFlag("0"));

        return AjaxResult.success("操作成功");
    }


    @Override
    @Transactional
    public AjaxResult withdraw(BigDecimal amount, String paymentPassword, HttpServletRequest request) {
        SzUser userInfo = userSession.getCurrentUserInfo(request);
        SzOtherRule otherRule = ruleCache.getOtherRule();

        if (StringUtil.isEmpty(userInfo.getPaymentPassword())){
            return AjaxResult.error("未设置支付密码！");
        }

        if (!paymentPassword.equals(userInfo.getPaymentPassword())){
            return AjaxResult.error("支付密码错误！");
        }

        if (szUserBankCardMapper.selectCount(new LambdaQueryWrapper<SzUserBankCard>().eq(SzUserBankCard::getUserId, userInfo.getId()).eq(SzUserBankCard::getDeleteFlag, "0")) == 0){
            return AjaxResult.error("请绑定银行卡后再进行提现！");
        }

        BigDecimal avil = BigDecimalChain.chain(userInfo.getSzWithdrawalBalance()).sub(userInfo.getFrozenAccount()).get();
        if (amount.compareTo(avil) > 0){
            return AjaxResult.error("账户可用提现余额不足！");
        }

        if (userInfo.getSzEnergy().compareTo(amount) < 0){
            return AjaxResult.error("能量值不足");
        }

        if (userInfo.getDeductionAmount().compareTo(BigDecimal.ZERO) != 0){
            return AjaxResult.error("非正常用户，完成还款后可正常提现");
        }

        if (amount.compareTo(BigDecimal.ZERO) == 0){
            return AjaxResult.success("操作成功");
        }

        SzUserBankCard bankCard = szUserBankCardMapper.selectOne(new LambdaQueryWrapper<SzUserBankCard>().eq(SzUserBankCard::getUserId, userInfo.getId()).eq(SzUserBankCard::getDeleteFlag, "0"));
        BigDecimal extract = BigDecimalChain.chain(amount).mul(otherRule.getExtractRatio()).get();
        BigDecimal revenue = BigDecimalChain.chain(amount).mul(otherRule.getRevenueRatio()).get();
        BigDecimal actualArrival = BigDecimalChain.chain(amount).sub(extract).sub(revenue).get();

        // 提现记录
        SzWithdrawalRecord withdrawalRecord = new SzWithdrawalRecord();
        withdrawalRecord.setUserId(userInfo.getId());
        withdrawalRecord.setMoney(amount);
        withdrawalRecord.setApplicationTime(LocalDateTime.now());
        withdrawalRecord.setState("1");
        withdrawalRecord.setExtractRatio(otherRule.getExtractRatio());
        withdrawalRecord.setRevenueRatio(otherRule.getRevenueRatio());
        withdrawalRecord.setExtractMoney(extract);
        withdrawalRecord.setRevenueMoney(revenue);
        withdrawalRecord.setEnergy(amount);
        withdrawalRecord.setAccount(bankCard.getCardId());
        withdrawalRecord.setWithdrawalMethod("2");
        withdrawalRecord.setActualArrival(actualArrival);
        szWithdrawalRecordMapper.insert(withdrawalRecord);

        // 更新余额
        userInfo.setSzWithdrawalBalance(BigDecimalChain.chain(userInfo.getSzWithdrawalBalance()).sub(amount).get());
        userInfo.setSzEnergy(BigDecimalChain.chain(userInfo.getSzEnergy()).sub(amount).get());
        szUserMapper.updateById(userInfo);

        // 提现余额变化记录
        SzWithdrawalDetail withdrawalDetail = new SzWithdrawalDetail();
        withdrawalDetail.setUserId(userInfo.getId());
        withdrawalDetail.setMoney(amount);
        withdrawalDetail.setFlowType("11");
        withdrawalDetail.setTakeoutId(withdrawalRecord.getId());
        withdrawalDetail.setCreateTime(LocalDateTime.now());
        szWithdrawalDetailMapper.insert(withdrawalDetail);

        // 能量值变化记录
//        SzEnergyRecord energyRecord = new SzEnergyRecord();
//        energyRecord.setUserId(userInfo.getId());
//        energyRecord.setCreateTime(LocalDateTime.now());
//        energyRecord.setEnergy(amount);
//        energyRecord.setType("2");
//        szEnergyRecordMapper.insert(energyRecord);

        return AjaxResult.success("操作成功");
    }

    @Override
    public AjaxResult setPaymentPassword(String paymentPassword, HttpServletRequest request) {
        SzUser userInfo = userSession.getCurrentUserInfo(request);

        if (StringUtil.isNotEmpty(userInfo.getPaymentPassword())) {
            return AjaxResult.error("支付密码已被设置");
        }

        if (!paymentPassword.matches("\\d+")) {
            return AjaxResult.error("支付密码仅能为数字");
        }

        if (paymentPassword.length() != 6) {
            return AjaxResult.error("支付密码位数必须为6位");
        }

        userInfo.setPaymentPassword(paymentPassword);
        szUserMapper.updateById(userInfo);
        return AjaxResult.success("操作成功");
    }

    @Override
    public AjaxResult withdrawRecord(HttpServletRequest request) {
        List<Map<String, Object>> list = szUserMapper.withdrawRecordSimple(userSession.getCurrentUserId(request));
        return AjaxResult.success(list);
    }

    /**
     * 手机号注册
     * @param user
     * @return
     */
    @Override
    public AjaxResult innerRegister(SzUser user) {
        log.info("innerRegister手机号注册参数："+user.toString());
        if (szUserMapper.selectCount(new LambdaQueryWrapper<SzUser>().eq(SzUser::getPhone, user.getPhone()).eq(SzUser::getIsSignOut, "0").eq(SzUser::getDeleteFlag,"0")) != 0){
            return AjaxResult.success("该手机号已被注册");
        }

        Long parentId = null;
        if (StringUtil.isNotEmpty(user.getInvitationParent())){
            parentId = this.getParentInvitationCode(user.getInvitationParent());
        }
        this.checkAccountHistory(user.getPhone());

        // 设置注册信息
        user.setAccountType("2"); // 商户
        user.setRegisterTime(LocalDateTime.now());
        user.setRecharge("0"); // 没参加过充值
        user.setWithdrawalLimitMonth(BigDecimal.ZERO);
        user.setBaseGoldBalance(BigDecimal.ZERO);
        user.setWelfareGoldBalance(BigDecimal.ZERO);
        user.setWelfareWithdrawalBalance(BigDecimal.ZERO);
        user.setInvitationCode(user.getInvitationCode());
        user.setInvitationParent(user.getInvitationParent());
        user.setSzWalletBalance(BigDecimal.ZERO);
        user.setSzWithdrawalBalance(BigDecimal.ZERO);
        user.setSzTeamReward(BigDecimal.ZERO);
        user.setSzRangeReward(BigDecimal.ZERO);
        user.setSzLateralReward(BigDecimal.ZERO);
        user.setSzRepeatbuyReword(BigDecimal.ZERO);
        user.setSzEnergy(BigDecimal.ZERO);
        user.setSzEnable("0");
        user.setAvatar(defaulAvatar);
        user.setVoucher(BigDecimal.ZERO);
        user.setDeductionAmount(BigDecimal.ZERO);
        user.setFrozenAccount(BigDecimal.ZERO);
        user.setPendingActivationBalance(BigDecimal.ZERO);
        user.setIsSignOut("0");
        user.setIsFrozen("0");
        szUserMapper.insert(user);

        if (parentId != null){
            SzPromotionTree tree = new SzPromotionTree();
            tree.setUserId(user.getId());
            tree.setParentId(parentId);
            tree.setCreateTime(LocalDateTime.now());
            szPromotionTreeMapper.insert(tree);
        }

        redisTemplate.delete(SystemConstant.getRegisterPrefix() + user.getPhone());
        return AjaxResult.success("注册成功");
    }

    /**
     * 新数字直播-礼物打赏
     * @param vo
     * @return
     */
    @Override
    public AjaxResult innerRewardWithGifts(RewardWithVO vo) throws Exception {
        return fiDigitalLivestreamingUserService.innerRewardWithGifts(vo);
    }

    /**
     * 购买数字直播2
     * @param userId
     * @return
     */
    @Override
    public AjaxResult buyLivestreaming2(String userId) {
        Long parentId = szUserMapper.listSzUserParentIdByUserId(userId);
        if (Objects.isNull(parentId)){
            return fiDigitalLivestreamingService.buyProduct(userId);
        }else{
            return fiDigitalLivestreamingService.buyProductByInvite(userId, parentId.toString());
        }
    }
}
